package com.ll.domain.classbase.schedul;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ll.base.util.DateUtil;
import com.ll.base.util.ScalarUtil;
import com.ll.dal.po.CoursePO;
import com.ll.dal.po.SignupPO;
import com.ll.domain.classbase.base.CourseBaseService;
import com.ll.domain.classbase.convert.CourseConvert;
import com.ll.domain.classbase.enums.CourseStatusEnum;
import com.ll.domain.classbase.enums.CourseTypeEnum;
import com.ll.domain.classbase.event.producer.AddCourserEvent;
import com.ll.domain.classbase.event.producer.UpdateCourserStatusEvent;
import com.ll.domain.user.base.UserBaseService;
import com.ll.domain.classbase.base.SignupBaseService;
import com.ll.domain.dingtalk.base.DingTalkMessageBaseService;
import com.ll.domain.classbase.enums.CourseIsNotifyEnum;
import com.ll.domain.classbase.enums.SingupStatusEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
public class CourseStatusJob {
    @Resource
    private  CourseBaseService courseBaseService;
    @Resource
    private  UserBaseService userBaseService;
    @Resource
    private  SignupBaseService signupBaseService;
    @Resource
    private  DingTalkMessageBaseService dingTalkMessageBaseService;
    @Resource
    private  ApplicationEventPublisher applicationEventPublisher;

    //提前6小时通知
    private final static int HOUR = 6;

    @Scheduled(cron = "0 */1 * * * ?")
    public void handlerCourseStatus() {
        try {
            this.notifyCourse();

            this.actionCourse();

            this.endCourse();
        }catch (Exception e){
            log.error("通知训练任务 thread id:{}, 执行失败了 {}", Thread.currentThread().getId(), e);
        }
    }

    /**
     * 提前通知课程
     */
    public void notifyCourse() {
        boolean result = true;
        Date notifyDate = DateUtil.addDateHour(HOUR);
        List<CoursePO> notifyList = courseBaseService.list(new LambdaQueryWrapper<CoursePO>()
                .eq(CoursePO::getStatus, CourseStatusEnum.未开始)
                .eq(CoursePO::getIsNotify, CourseIsNotifyEnum.未通知)
                .le(CoursePO::getStartTime, notifyDate));
        log.info("thread id:{}, 需要通知的课程 {}", Thread.currentThread().getId(), notifyList.size());
        if (ScalarUtil.isNotEmpty(notifyList)) {
            notifyList.forEach(r -> {
                dingTalkMessageBaseService.sendCourseNotify(r);
                r.setIsNotify(CourseIsNotifyEnum.已通知);
            });
            result = courseBaseService.updateBatchById(notifyList);
        }
        log.info("通知训练任务 thread id:{}, 执行结果{}", Thread.currentThread().getId(), result);
    }

    /**
     * 修改开始状态的课程
     */
    public void actionCourse() {
        boolean result = true;
        List<CoursePO> list = courseBaseService.list(new LambdaQueryWrapper<CoursePO>()
                .eq(CoursePO::getStatus, CourseStatusEnum.未开始)
                .le(CoursePO::getStartTime, new Date()));
        log.info("thread id:{}, 需要开始的课程 {}", Thread.currentThread().getId(), list.size());
        if (ScalarUtil.isNotEmpty(list)) {
            list.forEach(r -> r.setStatus(CourseStatusEnum.开始中));
            result = courseBaseService.updateBatchById(list);
        }
        log.info("开始训练任务 thread id:{}, 执行结果{}", Thread.currentThread().getId(), result);
    }

    public void endCourse() {
        boolean result = true;
        List<CoursePO> list = courseBaseService.list(new LambdaQueryWrapper<CoursePO>()
                .eq(CoursePO::getStatus, CourseStatusEnum.开始中)
                .le(CoursePO::getEndTime, new Date()));
        log.info("thread id:{}, 需要结束的课程 {}", Thread.currentThread().getId(), list.size());
        if (ScalarUtil.isNotEmpty(list)) {
            list.stream()
                    .forEach(r -> {
                        r.setStatus(CourseStatusEnum.已经结束);
                        if (r.getType() != CourseTypeEnum.积分训练) {
                            List<SignupPO> signupPOS = signupBaseService.queryListByCourseId(r.getId());
                            signupPOS.stream()
                                    .filter(s -> s.getStatus() == SingupStatusEnum.已报名)
                                    .forEach(s -> userBaseService.addIntegral(s.getDingTalkUserId(), -10));

                            if (r.getEndTime().getTime() - r.getStartTime().getTime() > (1000 * 60 * 50)) {
                                userBaseService.addIntegral(r.getDingTalkUserId(), 15);
                            }
                        } else {
                            userBaseService.addIntegral(r.getDingTalkUserId(), r.getApplicants() * 3);
                        }

                        //发送事件
                        applicationEventPublisher.publishEvent(new UpdateCourserStatusEvent(CourseConvert.PO2DTO(r)));

                    });
            result = courseBaseService.updateBatchById(list);
        }
        log.info("结束训练任务 thread id:{}, 执行结果{}", Thread.currentThread().getId(), result);
    }
}
